<template>
  <el-tree
      ref="treeRef"
      class="scrollbar-y"
      :load="loadTreeNode"
      lazy
      :props="{label: 'label', isLeaf: 'leaf', children: 'children'}"
      node-key="id"
      :expand-on-click-node="true"
      @node-click="handelNodeClick"
      @node-expand="handleNodeExpand">
    <template #default="{ node, data }">
      <div class="custom-tree-node">
        <i class="iconfont icon-24gf-folderOpen gradient-text" v-if="data.type === TreeNodeType.Dir"></i>
        <i class="iconfont icon-24gl-fileText" v-else></i>
        <span class="node-label">{{ data.label }}</span>
        <el-dropdown v-if="showOption">
          <i class="iconfont icon-gengduo opt-icon"></i>
          <template #dropdown>
            <el-dropdown-menu>
              <el-dropdown-item command="create" v-if="data.type === TreeNodeType.Dir">
                <div class="menu-item" @click.stop="handlePopCreateDirModal(data)">
                  <i class="iconfont icon-tianjiajiahaowubiankuang"></i>
                  <span>创建文件夹</span>
                </div>
              </el-dropdown-item>
              <el-dropdown-item command="rename">
                <div class="menu-item" @click.stop="handlePopRenameModal(data)">
                  <i class="iconfont icon-bianji"></i>
                  <span>重命名</span>
                </div>
              </el-dropdown-item>
              <el-dropdown-item command="delete">
                <div class="menu-item del-item" @click.stop="handleDelDir(data)">
                  <i class="iconfont icon-shanchu"></i>
                  <span>删除</span>
                </div>
              </el-dropdown-item>
            </el-dropdown-menu>
          </template>
        </el-dropdown>
      </div>
    </template>
  </el-tree>
  <el-dialog v-model="createDirModalVisible" title="创建文件夹" width="25%">
    <div class="flex align-center modal-row-input">
      <el-breadcrumb-item separator="/">{{ currentDirFileItem.label }}<span class="breadcrumb__separator">/</span>
      </el-breadcrumb-item>
      <el-input class="underline-input" v-model="dirName" placeholder="输入文件夹名称"></el-input>
      <el-button type="primary" @click="handleCreateDir" :loading="createDirLoading">创建</el-button>
    </div>
  </el-dialog>
  <el-dialog v-model="renameModalVisible" title="重命名" width="25%">
    <div>
      <div class="origin-name">原名称：{{ currentDirFileItem.label }}</div>
      <el-input style="margin: 10px 0;" class="underline-input" v-model="newName" placeholder="输入新的名称"></el-input>
      <el-button type="primary" @click="handleRename" :loading="renameLoading">确定</el-button>
    </div>
  </el-dialog>
</template>
<script setup>
import {ref} from 'vue';
import {ElMessage, ElMessageBox} from "element-plus";
import constants from '~/common/constants.js'
import api from "~/api/index.js";
import common from "~/common/common.js";

const emits = defineEmits(['click', 'expand', 'rename', 'delete', 'create'])
const props = defineProps({
  showOption: {
    type: Boolean,
    default: true
  }
})
const treeRef = ref()
const user = common.getLocalUser()
const uid = user.userId
const TreeNodeType = constants.TreeNodeType
const createDirModalVisible = ref(false)
const renameModalVisible = ref(false)
const createDirLoading = ref(false)
const renameLoading = ref(false)
const currentDirFileItem = ref({})
const dirName = ref('')
const newName = ref('')

const getFileListById = async (id) => {
  let result = []
  try {
    const res = await api.getDirFileList({
      uid,
      dir_id: id || ''
    })
    if (res.directories && res.directories.length) {
      res.directories.forEach((item) => {
        result.push({
          ...item,
          label: item.dir_name,
          type: TreeNodeType.Dir,
          leaf: false,
          parentId: id || '',
        })
      })
    }
    if (res.files && res.files.length) {
      res.files.forEach((item) => {
        result.push({
          ...item,
          label: item.file_name,
          type: TreeNodeType.File,
          leaf: true,
          parentId: id || '',
        })
      })
    }
  } catch (e) {

  }
  return result
}

const loadTreeNode = async (node, resolve) => {
  if (node.level === 0) {
    const result = await getFileListById()
    resolve(result)
  } else {
    if (node.isLeaf) {
      resolve([])
    } else {
      const result = await getFileListById(node.data.id)
      resolve(result)
    }
  }
}

const handlePopCreateDirModal = (nodeData) => {
  currentDirFileItem.value = nodeData || {}
  dirName.value = ''
  createDirModalVisible.value = true
}
/**
 * 更新树的子节点，包括更新根节点
 * @param parentNodeId
 * @returns {Promise<void>}
 */
const updateNodeChildren = async (parentNodeId) => {
  const data = await getFileListById(parentNodeId)
  if (parentNodeId) {
    const parentNode = treeRef.value.getNode(parentNodeId)
    parentNode.expand()
    treeRef.value.updateKeyChildren(parentNodeId, data)
  } else {
    treeRef.value.root.setData(data)
  }
}
const handleCreateDir = async () => {
  try {
    const dir_name = dirName.value.trim()
    if (!dir_name) {
      ElMessage.error('请输入文件夹名称')
      return
    }
    createDirLoading.value = true
    const parentId = currentDirFileItem.value.id || null
    const res = await api.createDir({
      uid,
      parent_dir_id: parentId,
      dir_name
    })
    createDirLoading.value = false
    if (res.data) {
      ElMessage.success('文件夹创建成功')
      createDirModalVisible.value = false
      treeRef.value.setCurrentKey(parentId)
      updateNodeChildren(parentId)
      let parentDataArr = []
      if (parentId) {
        const node = treeRef.value.getNode(parentId)
        if (node.parent) {
          parentDataArr = getParentNodeDataArr(node.parent)
        }
        parentDataArr.reverse()
      }
      emits('create', {nodeData: currentDirFileItem.value, parentDataArr})
    } else {
      ElMessage.error(res.message || '文件夹创建失败')
    }
  } catch (e) {
    createDirLoading.value = false
    console.log(e)
    ElMessage.error('文件夹创建异常')
  }
}
const handlePopRenameModal = (nodeData) => {
  currentDirFileItem.value = nodeData || {}
  newName.value = ''
  renameModalVisible.value = true
}
const handleRename = async () => {
  try {
    const name = newName.value.trim()
    if (!name) {
      ElMessage.error('请输入新的名称')
      return
    }
    renameLoading.value = true
    const id = currentDirFileItem.value.id
    let res
    if (currentDirFileItem.value.type === TreeNodeType.Dir) {
      res = await api.renameDir({
        uid,
        dir_id: id,
        new_dir_name: name,
      })
    } else {
      res = await api.renameFile({
        uid,
        file_id: id,
        new_file_name: name,
      })
    }
    renameLoading.value = false
    if (res.status === 'success') {
      ElMessage.success('重命名成功')
      renameModalVisible.value = false
      currentDirFileItem.value.label = name
      if (currentDirFileItem.value.type === TreeNodeType.Dir) {
        currentDirFileItem.value.dir_name = name
      } else {
        currentDirFileItem.value.file_name = name
      }
      emits('rename', currentDirFileItem.value)
    } else {
      ElMessage.error(res.message || '重命名失败')
    }
  } catch (e) {
    renameLoading.value = false
    console.log(e)
    ElMessage.error('重命名异常')
  }
}

const handleDelDir = async (nodeData) => {
  let result = false
  try {
    await ElMessageBox.confirm(`确定要删除【${nodeData.label}】这个${nodeData.type === TreeNodeType.Dir ? '文件夹' : '文件'}吗?`)
    const node = treeRef.value.getNode(nodeData.id)
    const parentNode = node.parent
    try {
      let res
      if (nodeData.type === TreeNodeType.Dir) {
        res = await api.deleteDir({
          uid,
          dir_id: nodeData.id
        })
      } else {
        res = await api.deleteFile({
          uid,
          file_id: nodeData.id
        })
      }
      if (res.status === 'success') {
        ElMessage.success('删除成功')
        if (parentNode.level === 0) {
          // 一级节点
          updateNodeChildren()
        } else {
          updateNodeChildren(parentNode.data.id)
        }
        result = true
        emits('delete', nodeData)
      } else {
        ElMessage.error(res.message || '删除失败')
      }
    } catch (e) {
      console.log(e)
      ElMessage.error('删除异常')
    }
  } catch (e) {
  }
  return result
}
const getParentNodeDataArr = (node) => {
  const parentArr = []
  const getParent = (node) => {
    if (node.parent) {
      parentArr.push({
        ...node.data
      })
      getParent(node.parent)
    }
  }
  getParent(node)
  return parentArr
}
let clickFlag = false
const handleNodeExpand = (nodeData) => {
  if (clickFlag) {
    clickFlag = false
    return
  }
  const node = treeRef.value.getNode(nodeData.id)
  treeRef.value.setCurrentKey(nodeData.id)
  let parentDataArr = []
  if (node.parent) {
    parentDataArr = getParentNodeDataArr(node.parent)
  }
  parentDataArr.reverse()
  emits('expand', {nodeData, parentDataArr})
}
const handelNodeClick = (nodeData) => {
  if (nodeData.type === TreeNodeType.File){
    return
  }
  clickFlag = true
  const node = treeRef.value.getNode(nodeData.id)
  treeRef.value.setCurrentKey(nodeData.id)
  let parentDataArr = []
  if (node.parent) {
    parentDataArr = getParentNodeDataArr(node.parent)
  }
  parentDataArr.reverse()
  emits('click', {nodeData, parentDataArr})
}
const expandTreeNode = (nodeData) => {
  const node = treeRef.value.getNode(nodeData.id)
  if (node) {
    node.expand()
    treeRef.value.setCurrentKey(nodeData.id)
  } else {
    /* 根节点 */
    treeRef.value.setCurrentKey(null)
    treeRef.value.root.childNodes.forEach((node) => {
      node.expanded = false
      node.isCurrent = false
    })
  }
}
const refreshNodeChildren = (nodeId) => {
  updateNodeChildren(nodeId)
}

defineExpose({
  handlePopCreateDirModal,
  getFileListById,
  handleDelDir,
  expandTreeNode,
  refreshNodeChildren,
  treeRef,
})
</script>

<style scoped lang="scss">
.el-tree {
  height: calc(100% - 40px);
  background: transparent;
}

.custom-tree-node {
  display: flex;
  align-items: center;
  font-size: 1rem;
  position: relative;
  width: 100%;
  .node-label {
    margin: 0 5px;
  }

  .iconfont {
    font-size: 1rem;
  }

  .icon-24gf-folderOpen {
    background-color: #FAD961;
    background-image: -webkit-linear-gradient(0deg, #FAD961 0%, #F76B1C 100%);
    background-image: -moz-linear-gradient(0deg, #FAD961 0%, #F76B1C 100%);
    background-image: -o-linear-gradient(0deg, #FAD961 0%, #F76B1C 100%);
    background-image: linear-gradient(0deg, #FAD961 0%, #F76B1C 100%);
  }
  .el-dropdown{
    position: absolute;
    right:10px;
  }

  .opt-icon {
    cursor: pointer;
    color: var(--el-text-color-secondary);
    //padding: 10px;
    font-size: 1.6rem;
    &:hover {
      color: var(--el-text-color-primary);
    }

  }
  .menu-item{
    display: flex;
    align-items: center;
    font-size: 1rem;
  }

}
.del-item{
  color: var(--el-color-error);
}
.modal-row-input {
  .el-breadcrumb__item {
    white-space: nowrap;
  }

  .underline-input {
    //width: 180px;
    margin-right: 10px;
  }

  .breadcrumb__separator {
    padding: 0 12px;
  }
}
</style>
